/*******************************************************************************
 * This file is part of blueprint4j www.blueprint4j.org.
 * 
 *     blueprint4j is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * 
 *     blueprint4j is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Lesser General Public License for more details.
 * 
 *     You should have received a copy of the GNU Lesser General Public License
 *     along with blueprint4j. If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package blueprint4j.apps;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

import blueprint4j.gui.db.Editor;

public class ApplicationLayoutLeftButtons implements ApplicationLayout {
	private boolean isBuilt=false;
	private JPanel main = new JPanel(new BorderLayout());
	private JPanel buttons = new JPanel(new GridBagLayout());
	private JComponent titleBar=null;
	private JComponent statusBar=null;
	private String currentItem = null;
	private List<String> menuItemsList = new ArrayList<String>();
	private Map<String, Editor> menuHashMap = new HashMap<String, Editor>();
	private Map<String, Image> iconsMap= new HashMap<String, Image>();
	private Map<String, KeyStroke> keyStrokeMap= new HashMap<String, KeyStroke>();
	private Map<String, ApplicationAction> menuActionHashMap = new HashMap<String, ApplicationAction>();

	private Color leftMenuBackgroundColor=new Color(65,112,165);
	private Color leftMenuForegroundColor=Color.WHITE;
	private Font leftMenuFont=null;
	
	public ApplicationLayoutLeftButtons(String defaultItem) {
		this.currentItem = defaultItem;
		JLabel l=new JLabel();
		leftMenuFont=l.getFont().deriveFont(Font.BOLD, 16);
	}

	@Override
	public void addInterface(String menu, Editor component) {
		menuItemsList.add(menu);
		menuHashMap.put(menu, component);
		isBuilt=false;
	}

	@Override
	public void addInterface(String menu, Image icon, Editor component) {
		iconsMap.put(menu,icon);
		addInterface(menu,component);
	}

	@Override
	public void addInterface(String menu, KeyStroke ks,Image icon, Editor component) {
		iconsMap.put(menu,icon);
		keyStrokeMap.put(menu,ks);
		addInterface(menu,component);
	}

	@Override
	public void addInterface(String menu, KeyStroke ks, Editor component) {
		keyStrokeMap.put(menu,ks);
		addInterface(menu,component);
	}

	@Override
	public void addAction(String menu, ApplicationAction action) {
		menuItemsList.add(menu);
		menuActionHashMap.put(menu, action);
		isBuilt=false;
	}

	@Override
	public void addAction(String menu, Image icon, ApplicationAction action) {
		iconsMap.put(menu,icon);
		addAction(menu,action);
	}

	@Override
	public void addAction(String menu, KeyStroke ks,Image icon, ApplicationAction action) {
		iconsMap.put(menu,icon);
		keyStrokeMap.put(menu,ks);
		addAction(menu,action);
	}

	@Override
	public void addAction(String menu, KeyStroke ks, ApplicationAction action) {
		keyStrokeMap.put(menu,ks);
		addAction(menu,action);
	}

	@Override
	public JComponent getComponent(JFrame frame) {
		if (!isBuilt) {
			build();
		}
		return main;
	}

	@Override
	public void selectInterface(final String menu) {
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				Editor editor;
				if (menuHashMap.containsKey(currentItem)) {
					editor=menuHashMap.get(currentItem);
					if (!editor.getEntityEditor().save()){
						return;
					}
					main.remove(editor.getComponent());
				}
				
				editor=menuHashMap.get(menu);
				editor.activated();
				final Editor finalEditor=editor;
				SwingUtilities.invokeLater(new Runnable() {

					@Override
					public void run() {
						main.add(finalEditor.getComponent());
						main.repaint();
						currentItem = menu;
					}
				});
			}

		});
	}

	private void build() {
		isBuilt=true;
		SwingUtilities.invokeLater(new Runnable() {

			@Override
			public void run() {
				main.removeAll();
				
				String currentList=null;

				buttons.removeAll();
				GridBagConstraints gbc=new GridBagConstraints();
				gbc.gridx=0;
				gbc.gridy=0;
				gbc.fill=GridBagConstraints.BOTH;
				
				for (String menuPath : menuItemsList) {
					int lastSplit = menuPath.lastIndexOf(MENU_SPLIT_CHARACTER);
					String menuName;
					String item;
					if (lastSplit == -1) {
						menuName = "";
						item=menuPath;
					} else {
						menuName = menuPath.substring(0, lastSplit);
						item=menuPath.substring(lastSplit+MENU_SPLIT_CHARACTER.length());
					}

					if (!menuName.equals(currentList)) {
						currentList=menuName;
						JLabel label=new JLabel(menuName);
						label.setForeground(leftMenuForegroundColor);
						label.setFont(leftMenuFont);
						label.setBorder(BorderFactory.createEmptyBorder(8,0,3,0));
						gbc.anchor=GridBagConstraints.WEST;
						buttons.add(label,gbc);
						gbc.gridy++;
					}
					JButton button;
					if (menuHashMap.containsKey(menuPath)){
						button=new JButton(new ALBAction(menuPath, item));
 					}else {
 						button=new JButton(new ApplicationActionWrapper(menuPath, item,menuActionHashMap.get(menuPath)));
					}
					button.setHorizontalAlignment(SwingConstants.LEFT);
					gbc.anchor=GridBagConstraints.EAST;
					
					JPanel bPanel=new JPanel(new BorderLayout());
					bPanel.setOpaque(false);
					bPanel.add(button,BorderLayout.CENTER);
					bPanel.setBorder(BorderFactory.createEmptyBorder(0,15,3,0));
					buttons.add(bPanel,gbc);
					gbc.gridy++;
				}
				
				JPanel left=new JPanel(new BorderLayout());
				buttons.setOpaque(false);
				buttons.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
				left.setBorder(BorderFactory.createLoweredBevelBorder());
				left.setBackground(leftMenuBackgroundColor);
				left.add(buttons,BorderLayout.NORTH);
				main.add(left,BorderLayout.WEST);
				if (titleBar!=null){
					main.add(titleBar,BorderLayout.NORTH);
				}
				if (statusBar!=null){
					main.add(statusBar,BorderLayout.SOUTH);
				}
			}
		});
	}
	
	class ALBAction extends AbstractAction {
		private static final long serialVersionUID = 1L;

		public String menuPath;

		ALBAction(String menuPath, String name) {
			super(name);
			this.menuPath = menuPath;
			if (iconsMap.containsKey(menuPath)){
				putValue(SMALL_ICON, new ImageIcon(iconsMap.get(menuPath)));
			}
			if (keyStrokeMap.containsKey(menuPath)){
				putValue(ACCELERATOR_KEY, keyStrokeMap.get(menuPath));
			}
		}

		public void actionPerformed(ActionEvent actionEvent) {
			selectInterface(menuPath);
		}
	}

	class ApplicationActionWrapper extends AbstractAction {
		private static final long serialVersionUID = 1L;

		public String menuPath;
		public ApplicationAction action;

		ApplicationActionWrapper(String menuPath, String name,ApplicationAction action) {
			super(name);
			this.menuPath = menuPath;
			this.action=action;
			if (iconsMap.containsKey(menuPath)){
				putValue(SMALL_ICON, new ImageIcon(iconsMap.get(menuPath)));
			}
			if (keyStrokeMap.containsKey(menuPath)){
				putValue(ACCELERATOR_KEY, keyStrokeMap.get(menuPath));
			}
		}

		public void actionPerformed(ActionEvent actionEvent) {
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					action.performAction();
				}
			});
		}
	}

	public void setTitleBar(JComponent titleBar) {
		this.titleBar=titleBar;
	}

	public void setStatusBar(JComponent statusBar) {
		this.statusBar=statusBar;
	}
	
}
